﻿<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Functions</title>
</head>
<body>
    <ul>
        Functions
        <li>Function objects are linked to Function.prototype (which is itself linked to Object.prototype).</li>
        <li>
            Every function is also created with two additional hidden properties:
            <ul>
                <li>the function's context</li>
                <li>the code that implements the function's behavior.</li>
            </ul>
        </li>
        <li>Every function object is also created with a prototype property. Its value is an object with a constructor property whose value is the function.</li>
        <li>This is distinct from the hidden link to Function.prototype.</li>
        <li>since functions are objects, functions can have methods</li>
        <li>The thing that is special about functions is that they can be invoked</li>
        <li>The function object created by a function literal contains a link to that outer context (An inner function also enjoys access to the parameters and variables of the functions it is nested within). <strong>This is called closure</strong></li>
    </ul>
    <ul>
        Invocation
        In addition to the declared parameters, every function receives two additional parameters:
        <li>
            <ul>
                <li>this</li>
                <li>arguments</li>
            </ul>
        </li>
        <li>
            <ul>
                <li>When a function is stored as a property of an object, we call it a <strong>method</strong>. When a method is invoked, <strong>this</strong> is bound to that object</li>
                <li>Methods that get their object context from this are called <strong>public methods</strong>.</li>
            </ul>
        </li>
        <li>When a function is not the property of an object, then it is invoked as a <strong>function</strong>. When a function is invoked with this pattern, <strong>this</strong> is bound to the global object.</li>
        <li>The Constructor Invocation Pattern. If a function is invoked with the new prefix, then a new object will be created with a hidden link to the value of the function's prototype member, and this will be bound to that new object.</li>
        <li>The Apply Invocation Pattern. Because JavaScript is a functional object-oriented language, <strong>functions can have methods</strong>.</li>
    </ul>
    <ul>
        Other comments
        <li>Because of a design error, arguments is not really an array.</li>
        <li>A function always returns a value. If the return value is not specified, then undefined is returned</li>
        <li>If the function was invoked with the new prefix and the return value is not an object, then this (the new object) is returned instead.</li>
    </ul>
    <script type="text/javascript">
        var initialization = function () {
            add = function (a, b) {
                return a + b;
            };
            // Create MyObject. It has a value and an increment
            // method. The increment method takes an optional
            // parameter. If the argument is not a number, then 1
            // is used as the default.
            MyObject = {
                value: 0,
                increment: function(inc) {
                    this.value += typeof inc === 'number' ? inc : 1;
                }
            };
            // Create a constructor function called Quo.
            // It makes an object with a status property.
            Quo = function(string) {
                this.status = string;
            };

            // Give all instances of Quo a public method
            // called get_status.
            Quo.prototype.get_status = function() {
                return this.status;
            };
        }();

        var functions = {
            methodInvocation: function () {

                MyObject.increment();
                var ok = MyObject.value == 1;

                MyObject.increment(2);
                return ok && MyObject.value == 3;
            }(),
            functionInvocation: function () {
                // Augment MyObject with a double method.
                MyObject.double = function () {
                    var that = this;    // Workaround.

                    var helper = function () {
                        that.value = that.value * 2;
                    };
                    helper();    // Invoke helper as a function.
                };

                // Invoke double as a method.
                MyObject.value = 3;
                MyObject.double();
                return MyObject.value == 6;
            }(),
            constructorInvocation: function () {
                // Make an instance of Quo.
                var myQuo = new Quo("confused");
                return myQuo.get_status();
            }(),
            applyInvocation: function () {
                // Make an array of 2 numbers and add them (array is arguments passed to add method)
                var array = [3, 4];
                var ok = add.apply(null, array) == 7;

                // Make an object with a status member.
                var statusObject = {
                    status: 'A-OK'
                };

                // statusObject does not inherit from Quo.prototype,
                // but we can invoke the get_status method on
                // statusObject even though statusObject does not have
                // a get_status method.
                return ok && Quo.prototype.get_status.apply(statusObject) == 'A-OK';
            }(),
            argumentsExample: function() {
                // Make a function that adds a lot of stuff.
                // Note that defining the variable sum inside of
                // the function does not interfere with the sum
                // defined outside of the function. The function
                // only sees the inner one.

                var sum = function () {
                    var i, sum = 0;
                    for (i = 0; i < arguments.length; i += 1) {
                        sum += arguments[i];
                    }
                    return sum;
                };

                return sum(4, 8, 15, 16, 23, 42) == 108;
            }(),
        };
    </script>
</body>
</html>
